<?php

namespace app\home\controller;

use app\common\controller\Home;

//引入底层控制器
use think\Controller;

//控制器 Controller
class Index extends Home
{
    //所有的控制器方法都不需要登录
    public $NoLogin = ["*"];

    public function __construct()
    {
        //继承底层的构造函数
        parent::__construct();

        //公共区域中加载模型，那么下面所有的方法中都可以使用这个模型
        $this->BusinessModel = model('Business.Business');
        $this->SubjectModel = model('Subject.Subject');
        $this->ChapterModel = model('Subject.Chapter');
        $this->CommentModel = model('Subject.Comment');
        $this->OrderModel = model('Subject.Order');
    }

    // 会员首页
    public function index()
    {
        //按照时间降序查询
        $top = $this->SubjectModel->order('createtime desc')->limit(5)->select();

        $list = $this->SubjectModel->order('id desc')->limit(8)->select();

        // var_dump(collection($top)->toArray());
        // exit;

        $data = [
            'top' => $top,
            'list' => $list
        ];

        //赋值数据到模板中去
        $this->assign($data);

        //渲染一个模板页面 V = View
        return $this->view->fetch();
    }

    // 注册
    public function register()
    {

        if ($this->request->isPost()) {
            // 类等与：$mobile = isset($_POST['mobile']) ? trim($_POST['mobile']) : '';
            $mobile = $this->request->param('mobile', '', 'trim');
            $password = $this->request->param('password', '', 'trim');

            // 判断一下密码是否为空，给个提示
            if (empty($password)) {
                $this->error('密码为空，请填写密码');
                exit;
            }

            // 生成一个密码盐，需要封装一个函数
            $salt = randstr();
            // 密码加密
            $password = md5($password . $salt);

            // 查询出云课堂的渠道来源的ID信息，数据库查询
            // 查询整条数据
            // $source = model('common/Business/Source')->where(['name' => ['LIKE', '%云课堂%']])->find();

            // 只查询一个字段
            // $sourceid = model('common/Business/Source')->where(['name' => ['LIKE', '%云课堂%']])->value('id');

            // 组装数据
            $data = [
                'mobile' => $mobile,
                'nickname' => $mobile,
                'password' => $password,
                'salt' => $salt,
                'gender' => '0', //性别
                'deal' => '0', //成交状态
                'money' => '0', //余额
                'auth' => '0', //实名认证
            ];

            // 单独判断是否有获取到sourceid
            $data['sourceid'] = model('common/Business/Source')->where(['name' => ['LIKE', '%云课堂%']])->value('id');

            // 执行插入，返回自增的条数
            $result = $this->BusinessModel->validate('common/Business/Business')->save($data);

            if ($result === FALSE) {
                //失败
                $this->error($this->BusinessModel->getError());
                exit;
            } else {
                //注册，跳转
                $this->success('注册成功', url('home/index/login'));
                exit;
            }
        }


        // 访问地址：www.fast.com/index.php/home/index/register
        //渲染模板 application/home/view/Index/register.html
        return $this->view->fetch();
    }

    // 登录
    public function login()
    {
        // 判断是否为微信浏览器访问
        if (Wechat()) {
            $openid = session('openid') ? session('openid') : '';

            if (empty($openid)) {
                $this->redirect(url('home/wechat/oauth'));
                exit;
            }
        }

        // 判断是否接收到请求
        if ($this->request->isPost()) {
            // 获取数据
            $mobile = $this->request->param('mobile', '', 'trim');
            $password = $this->request->param('password', '', 'trim');

            // 根据手机号老查询数据存不存在，单条查询
            $business = $this->BusinessModel->where(['mobile' => $mobile])->find();
            // 打印单条数据，使用toArray()这个方法
            // var_dump($business->toArray());
            // exit;

            // 判断用户是否存在
            if (!$business) {
                $this->error('用户不存在');
                exit;
            }
            // 验证密码盐，加密密码
            $salt = $business['salt'];
            $password = md5($password . $salt);

            // 判断密码是否正确
            if ($password != $business['password']) {
                $this->error('密码不正确');
                exit;
            }

            // 当资料中的openid为空的时候 就更新 
            if (empty($business['openid'])) {
                //判断是否有openid
                $openid = session('openid') ? session('openid') : '';

                if (!empty($openid)) {
                    $update = [
                        'id' => $business['id'],
                        'openid' => $openid
                    ];

                    $result = $this->BusinessModel->isUpdate(true)->save($update);

                    if ($result === FALSE) {
                        $this->error('授权绑定用户失败');
                        exit;
                    }
                }
            }

            // 保存cookie信息
            $cookie = [
                'id' => $business['id'],
                'mobile' => $business['mobile']
            ];

            // 存放到cookie中，关闭后自动销毁
            cookie('business', $cookie);

            // 跳转到会员中心
            $this->success('登陆成功！', url('home/business/index'));
            exit;
        }


        // 访问地址：www.fast.com/index.php/home/index/register
        //渲染模板 application/home/view/Index/register.html
        return $this->view->fetch();
    }

    // 搜索
    public function search()
    {

        // 判断是否有ajax请求过来
        if ($this->request->isAjax()) {
            // 1.接收ajax传递的参数
            $page = $this->request->param('page', 1, 'trim');
            $limit = $this->request->param('limit', 10, 'trim');
            $search = $this->request->param('search', '', 'trim');

            // 7.定义一个条件变量
            $where = [];

            // 8.进行条件判断（搜索框），如果搜索框不为空
            if (!empty($search)) {
                // 进行模糊查询
                $where['title'] = ['LIKE', "%$search%"];
            }

            // 2.查询数据总数 
            $count = $this->SubjectModel->where($where)->count();

            // 3.偏移量：当来到第二页的时候，初始为2，不再为1
            $start = ($page - 1) * $limit;

            // 4.查询到课程表的数量
            // 这里使用到了链表查询，就直接使用一个with(['链表的方法'])
            $list = $this->SubjectModel
                ->with(['category'])
                ->where($where)
                ->order('createtime desc')
                ->limit($start, $limit)
                ->select();

            // 5.组装数据
            $data = [
                'list' => $list,
                'count' => $count
            ];

            // 测试数据是否拿到
            // var_dump(collection($list)->toArray());
            // exit;

            // 6.判断数据是否为空，不为空则返回数据回去
            if (empty($list)) {
                $this->error('暂无更多数据');
                exit;
            } else {
                $this->success('成功返回数据', null, $data);
                exit;
            }
        }

        // 模板渲染
        return $this->view->fetch();
    }

    // 详情
    public function info()
    {
        // 1.获取pid，点击的详情页面
        $pid = $this->request->param('pid', 0, 'trim');

        // 2.判断课程是否存在
        $subject = $this->SubjectModel->find($pid);

        // 3.如果不存在，提醒，跳转回到原页面
        if (!$subject) {
            $this->error('该课程不存在！', url('home/index/search'));
        }

        // 4.查询课程的章节
        $chapter = $this->ChapterModel->where(['subid' => $pid])->select();

        // 5.查询课程的评论
        $comment = $this->CommentModel->with(['business'])->where(['subid' => $pid])->limit(3)->select();

        // 判断是否有登录
        $business = $this->auth(false);

        // 如果有登录
        if ($business) {
            // 获取用户的id
            $busid = $business['id'];
            // 获取点赞的数组（数组里面包含的是点赞的用户id）
            $likes = $subject['likes'];
            // 将点赞人的id转换为数组
            if (empty($likes)) {
                // 如果为空，赋值为空数组
                $likes = [];
            } else {
                // 如果不为空，就转换数组
                $likes = explode(',', $likes);
            }

            // 判断当前登录的人id在不在点赞的数组中，如果在，说明点赞了
            //判断当前登录的人id 在不在 点赞的数组中 如果在就说明点过赞
            if (in_array($busid, $likes)) {
                // 将点赞的状态变为true
                $subject['like_status'] = true;
            } else {
                // 将点赞的状态变为false
                $subject['like_status'] = false;
            }
        } else {
            // 没有登录，让状态为没有点赞
            $subject['like_status'] = false;
        }

        // 将数据赋值给模板
        $this->assign([
            'subject' => $subject,
            'chapter' => $chapter,
            'comment' => $comment,
        ]);

        // 模板渲染
        return $this->view->fetch();
    }

    // 详情点赞的方法
    public function like()
    {
        // 判断是否有ajax请求过来
        if ($this->request->isAjax()) {
            // 接收ajax的参数
            $subid = $this->request->param('subid', 0, 'trim');
            $status = $this->request->param('status', '', 'trim');

            // 判断状态是否在数组里面[add, romove]
            if (!in_array($status, ['add', 'remove'])) {
                $this->error('点赞状态有问题');
                exit;
            }

            // 判断是否有登录
            $business = $this->auth(false);

            // 如果没有登录，让其登录
            if (!$business) {
                $this->error('请登录');
                exit;
            }

            //判断课程是否存在
            $subject = $this->SubjectModel->where(['id' => $subid])->find();

            // 如果不存在，就提示
            if (!$subject) {
                $this->error('课程不存在');
                exit;
            }

            // 获取点赞的数组，里面包含了用户的id
            $likes = empty($subject['likes']) ? [] : explode(',', $subject['likes']);

            // 如果用户的id在点赞的数组里面，说明点过赞
            // 这时要做取消点赞
            if (in_array($business['id'], $likes)) {
                // 查找到数组里面的这个用户id
                $pos = array_search($business['id'], $likes);

                //删除这个用户的id在数组里面
                unset($likes[$pos]);
            } else {
                //不在，就说明没点过赞，要点赞
                $likes[] = $business['id'];
            }

            //会怕存在遗漏 去重 保证唯一性
            $likes = array_unique($likes);
            $likes = implode(',', $likes);

            // 组装新的数据，进行更新
            $data = [
                'id' => $subid,
                'likes' => $likes
            ];

            // 将数据进行更新
            $result = $this->SubjectModel->isUpdate(true)->save($data);

            // 判断更新的清空
            if ($result === FALSE) {
                // 更新失败
                $msg = $status == "add" ? "点赞失败" : "取消点赞失败";
                $this->error($msg);
                exit;
            } else {
                // 更新成功
                $msg = $status == "add" ? "点赞成功" : "取消点赞成功";
                $this->success($msg);
                exit;
            }
        }
    }

    // 查看更多评论的方法
    public function comment_list()
    {
        // 判断是否有ajax发送过来
        if ($this->request->isAjax()) {
            // 1.获取课程id，点击的详情页面
            $pid = $this->request->param('pid', 0, 'trim');

            // 1.接收ajax传递的参数
            $page = $this->request->param('page', 1, 'trim');
            $limit = $this->request->param('limit', 10, 'trim');

            // 2.偏移量：当来到第二页的时候，初始为2，不再为1
            $start = ($page - 1) * $limit;

            // 2.判断课程是否存在
            $subject = $this->SubjectModel->find($pid);

            // 3.如果不存在，提醒，跳转回到原页面
            if (!$subject) {
                $this->error('该课程不存在！', url('home/index/search'));
            }

            // 3.查询课程的评论，这里使用了关联查询
            $comment = $this->CommentModel->with(['business'])->where(['subid' => $pid])->order('createtime desc')->limit($start, $limit)->select();

            // 拿到所有评论的数据
            $list = collection($comment)->toArray();
            // var_dump($list);
            // exit;

            // 4.拿到数据总数
            $listall = count($comment);

            // 组装数据，拿到所有的评论数以及
            $data = [
                'list' => $list,
                'count' => $listall
            ];

            if (empty($listall)) {
                $this->error('暂无更多数据');
                exit;
            } else {
                $this->success('成功返回数据', null, $data);
                exit;
            }
        }

        // 模板渲染
        return $this->view->fetch();
    }

    // 立即购买的方法
    public function buy()
    {
        // 判断是否有ajax请求
        if ($this->request->isAjax()) {
            // 接收ajax传递过来的参数
            $subid = $this->request->param('subid', 0, 'trim');

            //判断课程是否存在
            $subject = $this->SubjectModel->find($subid);

            if (!$subject) {
                $this->error('课程不存在');
                exit;
            }

            //判断是否有登录，等录方法，已经拿到了值
            $business = $this->auth(false);
            if (!$business) {
                $this->error('请先登录');
                exit;
            }

            //查询当前用户是否有购买过课程
            $where = [
                'busid' => $business['id'],
                'subid' => $subid
            ];
            $order = $this->OrderModel->where($where)->find();

            //判断是否有重复购买课程
            if ($order) {
                $this->error('您已购买过该课程');
                exit;
            }

            /**
             * 数据库事务
             * subject_order 课程订单 插入
             * business 用户余额 更新
             * business_record 消费记录 插入
             */

            //  加载模型
            $OrderModel = model('Subject.Order');
            $BusinessModel = model('Business.Business');
            $RecordModel = model('Business.Record');

            // 开启事务
            $OrderModel->startTrans();
            $BusinessModel->startTrans();
            $RecordModel->startTrans();

            // 判断用户余额是否充足
            $money = empty($business['money']) ? 0 : $business['money'];
            $price = empty($subject['price']) ? -1 : $subject['price'];
            if ($price < 0) {
                $this->error('课程的价格有误，无法进行购买');
                exit;
            }

            // 这里使用了bcsub方法，高精度的浮点数相减
            //两个高精度的浮点数相减
            $UpdateMoney = bcsub($money, $price, 2);

            //判断用户余额是否能够买，用户余额不足
            if ($UpdateMoney < 0) {
                $this->error('您的余额不足，请先充足');
                exit;
            }


            //生成课程的订单号
            $code = build_code('SUB');

            // 组装订单的数据，进行插入
            $OrderData = [
                'subid' => $subid,
                'busid' => $business['id'],
                'total' => $price,
                'code' => $code,
            ];
            // 执行插入
            $OrderStatus = $OrderModel->validate('common/Subject/Order')->save($OrderData);
            // 如果插入失败
            if ($OrderStatus === FALSE) {
                $this->error($OrderModel->getError());
                exit;
            }

            // 更新用户余额，组装数据
            $BusinessData = [
                'id' => $business['id'],
                'money' => $UpdateMoney
            ];

            //验证器
            $validate = [
                [
                    'money' => 'require|number|>=:0'
                ],
                [
                    'money.require' => '余额未知',
                    'money.number' => '余额必须是数字',
                    'money.>=' => '余额必须是大于等于0元',
                ]
            ];
            // 执行更新语句
            $BusinessStatus = $BusinessModel->validate(...$validate)->isUpdate(true)->save($BusinessData);
            // 如果更新失败
            if ($BusinessStatus === FALSE) {
                // 回滚撤销到第一步（插入订单号）
                $OrderModel->rollback();
                $this->error($BusinessModel->getError());
                exit;
            }

            // 封装插入消费记录表信息
            $title = $subject['title'];
            $content = "您购买了课程【{$title}】花费了：￥ $price 元";

            // 组装消费记录表数据
            $RecordData = [
                'total' => -$price,
                'busid' => $business['id'],
                'content' => $content
            ];
            // 执行插入语句
            $RecordStatus = $RecordModel->validate('common/Business/Record')->save($RecordData);
            // 如果插入失败
            if ($RecordStatus === FALSE) {
                // 撤销回滚，回到第一步（插入订单号）
                $BusinessModel->rollback();
                $OrderModel->rollback();
                $this->error($RecordModel->getError());
                exit;
            }

            // 如果三个中，有其中一个失败了，则进行撤销回滚
            //总的判断
            if ($OrderStatus === FALSE || $BusinessStatus === FALSE || $RecordStatus === FALSE) {
                $RecordModel->rollback();
                $BusinessModel->rollback();
                $OrderModel->rollback();
                $this->error('购买课程失败');
                exit;
            }
            // 如果三个都没有失败，则可以提交事务了
            $OrderModel->commit();
            $BusinessModel->commit();
            $RecordModel->commit();

            if (!empty($business['openid'])) {
                //组装数据
                $data = [
                    'touser' => $business['openid'],
                    'template_id' => 'wKrnxsM0wYhZ6zeRqhHuk6jjn1K_HIawQX4fG35K06o',
                    'url' => url('home/index/info', ['pid' => $subid], true, true),
                    'data' => [
                        'content' => $title,
                        'price' => $price,
                    ]
                ];

                $WechatController = new \app\home\controller\Wechat();

                $WechatController->template($data);
            }

            $this->success('购买课程成功');
            exit;
        }
    }

    // 视频播放的方法
    public function play()
    {
        // 判断是否是ajax请求
        if ($this->request->isAjax()) {
            // 接收ajax传递过来的参数
            $subid = $this->request->param('subid', 0, 'trim');
            $cid = $this->request->param('cid', 0, 'trim');

            // 判断课程是否存在
            $subject = $this->SubjectModel->find($subid);
            if (!$subject) {
                $this->error('课程不存在');
                exit;
            }

            // 判断章节是否存在
            $chapter = $this->ChapterModel->find($cid);
            // 如果章节不存在
            if (!$chapter) {
                //就默认去查找到该课程的第一个章节
                $chapter = $this->ChapterModel->where(['subid' => $subid])->order('id asc')->find();

                if (empty($chapter)) {
                    $this->error('该课程无章节');
                    exit;
                }
            }

            //判断是否有登录
            $business = $this->auth(false);
            if (!$business) {
                $this->error('请先登录');
                exit;
            }

            //查询当前用户是否有购买过课程
            $where = [
                'busid' => $business['id'],
                'subid' => $subid
            ];
            $order = $this->OrderModel->where($where)->find();

            //订单不存在，就说明没有买过课程
            if (!$order) {
                $this->success('请先购买课程', null, ['status' => 'buy']);
                exit;
            } else {
                $this->success('已购买', null, $chapter);
                exit;
            }
        }
    }

    // 退出
    public function logout()
    {
        // 清除cookie
        cookie('business', null);
        // 给个提示信息，跳转
        $this->success('退出成功', url("home/index/login"));
        exit;
    }
}
